import logger from '../core/logger';
import { BUNDLE_NAME } from '../core/dict';
import deviceManager from '@ohos.distributedDeviceManager';

export default class remoteDeviceManage {
  private callback: () => void = null;
  private authCallback: () => void = null;
  public deviceList: Array<deviceManager.DeviceBasicInfo> = [];
  public discoverList: Array<deviceManager.DeviceBasicInfo> = [];
  private deviceManager: deviceManager.DeviceManager | null = null;

  registerDeviceListCallback(callback) {
    try {
      if (!this.deviceManager)
        this.deviceManager = deviceManager.createDeviceManager(BUNDLE_NAME);
      this.registerDeviceListCallbackImplement(callback);
    } catch (error) {
      logger.error(error)
    }
  }

  changeStateOnline(device: deviceManager.DeviceBasicInfo) {
    try {
      this.discoverList = [];
      this.deviceList.push(device);
      let list = this.deviceManager.getAvailableDeviceListSync();
      if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined')
        this.deviceList = list;
      this.callback();
    } catch (e) {
      logger.error(e);
    }
  }

  changeState(device: deviceManager.DeviceBasicInfo) {
    try {
      if (this.deviceList.length > 0) {
        let list = [];
        for (let i = 0; i < this.deviceList.length; i++) {
          if (this.deviceList[i].deviceId !== device.deviceId)
            list[i] = device;
        }
        this.deviceList = list;
      }
      this.callback();
    } catch (e) {
      logger.error(e);
    }
  }

  registerDeviceListCallbackImplement(callback) {
    try {
      this.callback = callback;
      if (this.deviceManager === undefined) {
        this.callback();
        return;
      }
      let list = this.deviceManager?.getAvailableDeviceListSync();
      if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined')
        this.deviceList = list;
    } catch (error) {
      logger.error(error);
    }
    this.callback();
    try {
      this.deviceManager.on('deviceStateChange', (data) => {
        if (data === null)
          return;
        switch (data.action) {
          case deviceManager.DeviceStateChange.AVAILABLE:
            this.changeStateOnline(data.device);
            break;
          case deviceManager.DeviceStateChange.UNAVAILABLE:
            this.changeState(data.device);
            break;
        }
      });
      this.deviceManager.on('discoverSuccess', (data) => {
        if (data === null)
          return;
        this.deviceFound(data);
      });
    } catch (error) {
      logger.error(error);
    }
    this.startDeviceDiscovery();
  }

  deviceFound(data) {
    for (let i = 0; i < this.discoverList.length; i++) {
      if (this.discoverList[i].deviceId === data.device.deviceId)
        return;
    }
    this.discoverList[this.discoverList.length] = data.device;
    this.callback();
  }

  startDeviceDiscovery() {
    try {
      let discoverParam = {
        discoverTargetType: 1
      };
      let filterOptions = {
        availableStatus: 0
      };
      this.deviceManager?.startDiscovering(discoverParam, filterOptions);
    } catch (error) {
      logger.error(error);
    }
  }

  unregisterDeviceListCallback() {
    try {
      this.deviceManager?.stopDiscovering();
      this.deviceManager.off('deviceStateChange');
      this.deviceManager.off('discoverSuccess');
      this.deviceManager.off('discoverFailure');
      this.deviceManager.off('serviceDie');
    } catch (error) {
      logger.error(error);
    }
    this.deviceList = [];
    this.discoverList = [];
  }

  authenticateDevice(device: deviceManager.DeviceBasicInfo, callBack) {
    for (let i = 0; i < this.discoverList.length; i++) {
      try {
        if (this.discoverList[i].deviceId !== device.deviceId)
          continue;
        let bindParam = {
          bindType: 1,
          appName: 'm_manga',
          targetPkgName: BUNDLE_NAME
        };
        this.deviceManager?.bindTarget(device.deviceId, bindParam, (err) => {
          if (err) {
            logger.error(err);
            this.authCallback = null;
            return;
          }
          this.authCallback = callBack;
        })
      } catch (error) {
        logger.error(error);
      }
    }
  }
}